import { useRouter } from "next/router"; import { api } from "@/src/utils/api"; import { useHasProjectAccess } from "@/src/features/rbac/utils/checkProjectAccess"; import { Card, CardContent, CardHeader, CardTitle, } from "@/src/components/ui/card"; import { DeleteModelButton } from "@/src/features/models/components/DeleteModelButton"; import { EditModelButton } from "@/src/features/models/components/EditModelButton"; import { CloneModelButton } from "@/src/features/models/components/CloneModelButton"; import { JSONView } from "@/src/components/ui/CodeJsonViewer"; import Link from "next/link"; import { Button } from "@/src/components/ui/button"; import { getMaxDecimals } from "@/src/features/models/utils"; import Decimal from "decimal.js"; import { PriceUnitSelector } from "@/src/features/models/components/PriceUnitSelector"; import { useMemo } from "react"; import { usePriceUnitMultiplier } from "@/src/features/models/hooks/usePriceUnitMultiplier"; import Generations from "@/src/components/table/use-cases/observations"; import Page from "@/src/components/layouts/page"; import { SquareArrowOutUpRight } from "lucide-react"; export default function ModelDetailPage() { const router = useRouter(); const { priceUnit, priceUnitMultiplier } = usePriceUnitMultiplier(); const projectId = router.query.projectId as string; const modelId = router.query.modelId as string; const hasWriteAccess = useHasProjectAccess({ projectId, scope: "models:CUD", }); const { data: model, isLoading } = api.models.getById.useQuery( { projectId, modelId }, { enabled: !!projectId && !!modelId }, ); const maxDecimals = useMemo( () => Math.max( ...Object.values(model?.prices ?? {}).map((price) => getMaxDecimals(price, priceUnitMultiplier), ), ), [model?.prices, priceUnitMultiplier], ); // If not found, redirect to models page if (!isLoading && !model) { return (
Model not found
); } const isLangfuseModel = !Boolean(model?.projectId); if (isLoading || !model) { return
Loading...
; } return ( {hasWriteAccess && (!isLangfuseModel ? ( <> { void router.push(`/project/${projectId}/settings/models`); }} /> ) : ( ))} ), }} >
Model configuration
Match Pattern
{model.matchPattern}
Maintained by
{isLangfuseModel ? "Langfuse" : "User"}
Tokenizer
{model.tokenizerId || "None"}
{model.tokenizerId && (
Tokenizer Config
                  
                
)}
Pricing
Usage Type Price {priceUnit}
{Object.entries(model.prices).map(([usageType, price]) => (
{usageType} $ {new Decimal(price) .mul(priceUnitMultiplier) .toFixed(maxDecimals)}
))}
Model observations
); }